home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_091 / adlcomp / adllex.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  9KB  |  411 lines

  1.     /***************************************************************\
  2.     *                                *
  3.     *    adllex.c - Lexical anylizer for adlcomp.        *
  4.     *    Copyright 1987 by Ross Cunniff.                *
  5.     *                                *
  6.     \***************************************************************/
  7.  
  8. #include <ctype.h>
  9. #include <stdio.h>
  10.  
  11. #include "adltypes.h"
  12. #include "adldef.h"
  13. #include "vstring.h"
  14. #include "adlprog.h"
  15. #include "adlcomp.h"
  16.  
  17. /* adlchr( c ) is TRUE iff c is a valid character in a token */
  18.  
  19. #define adlchr( c ) (                \
  20.             isalnum( c ) ||        \
  21.             ( c == '_' ) ||        \
  22.             ( c == '%' ) ||        \
  23.             ( c == '$' ) ||        \
  24.             ( c == '.' ) ||        \
  25.             ( c == '-' )        \
  26.         )
  27.  
  28. /*   */
  29.  
  30. /***************************************************************\
  31. *                                *
  32. *    Global variables                    *
  33. *                                *
  34. \***************************************************************/
  35.  
  36. char    token[ 512 ],        /* Last token read            */
  37.     *EOFMSG = "Unexpected EOF.\n";    /* Message for EOF        */
  38.  
  39. int16    t_val,            /* Value of last token read        */
  40.     t_type,            /* Type of last token read        */
  41.     numerr    = 0,        /* Number of errors encountered        */
  42.     numwarn = 0,        /* Number of warnings encountered    */
  43.     numline = 1;        /* Number of lines read            */
  44.  
  45. extern
  46. int16    debugging,        /* Are we generating FILE and LINE code? */
  47.     inrout,            /* Are we inside a routine definition?    */
  48.     filenum;        /* Current file number.            */
  49.  
  50. FILE    *infile;        /* Current input file            */
  51. char    inname[ 512 ];        /* Name of current input file        */
  52.  
  53. /*   */
  54.  
  55.     /***************************************************************\
  56.     *                                *
  57.     *    lexer() - return the next input token from the input    *
  58.     *    stream in the form of a value and a type.        *
  59.     *                                *
  60.     \***************************************************************/
  61.  
  62. lexer()
  63. {
  64.     int16 t;
  65.  
  66.     if( gettoken( token ) == EOF ) {
  67.     /* We reached the end of file. */
  68.     t_type = EOF;
  69.     return;
  70.     }
  71.  
  72.     if( isnumber( token ) ) {
  73.     /* This token is a constant number. */
  74.     t_val = atoi( token );
  75.     t_type = CONST;
  76.     return;
  77.     }
  78.  
  79.     else if( adlchr( *token ) ) {
  80.     if( *token == '%' ) {
  81.         /* This token should be an argument number */
  82.         if( !isnumber( token + 1 ) )
  83.         error( "Illegal argument number.\n" );
  84.         t_val = atoi( token + 1 );
  85.         t_type = ARGUMENT;
  86.         return;
  87.     }
  88.  
  89.     /* This token should be an identifier. */
  90.     if( !adlident( token ) )
  91.         error( "Illegal token.\n" );
  92.  
  93.     t = lookup( token, &t_val, 0 );
  94.     if( t >= 0 ) {
  95.         /* This token has already been declared. */
  96.         t_type = t;
  97.         return;
  98.     }
  99.     else {
  100.         /* This token has not previously been declared */
  101.         t_type = UNDECLARED;
  102.         return;
  103.     }
  104.     }
  105.  
  106.     else if( *token == '"' ) {
  107.     /* This token is a compile time string */
  108.     t_val = newstr( token + 1 );
  109.     t_type = STRING;
  110.     return;
  111.     }
  112.  
  113.     else {
  114.     /* This token is punctuation */
  115.     t_type = *token;
  116.     return;
  117.     }
  118. }
  119.  
  120. /*   */
  121.  
  122.     /***************************************************************\
  123.     *                                *
  124.     *    gettoken( s ) - returns the next token from infile in    *
  125.     *    s.  A token is a number, an identifier, a string,    *
  126.     *    or punctuation.                        *
  127.     *                                *
  128.     \***************************************************************/
  129.  
  130. gettoken( s )
  131. char    *s;
  132. {
  133.     int ch;
  134.     int count = 0;
  135.  
  136.     ch = eatwhite();        /* Get rid of unneeded white space    */
  137.  
  138.     if( ch == '"' )
  139.     /* Get a string */
  140.     return getstring( s );
  141.  
  142.     else {
  143.     /* Get an identifier, number, or argument. */
  144.     while( adlchr( ch ) ) {
  145.         count++;
  146.         *s++ = ch;
  147.         ch = mygetc();
  148.     }
  149.     if( count ) {
  150.         /* We read more than one character. */
  151.         if( ch != EOF )
  152.         /* We read a character which should be read later */
  153.         ch = myunget( ch );
  154.     }
  155.     else
  156.         *s++ = ch;
  157.     *s = '\0';
  158.     return ch;
  159.     }    /* else */
  160. }    /* gettoken */
  161.  
  162. /*   */
  163.  
  164.     /***************************************************************\
  165.     *                                *
  166.     *    eatwhite() - eats up white space and comments from    *
  167.     *    the infile.                        *
  168.     *                                *
  169.     \***************************************************************/
  170.  
  171. eatwhite()
  172. {
  173.     int ch;
  174.     char s[ 512 ];
  175.  
  176.     for(    ch = mygetc();
  177.         (ch == ' ')||(ch == '\t')||(ch == '{')||(ch == '\n');
  178.         ch = mygetc() ) {
  179.     if( ch == '{' ) {
  180.         for( ch = mygetc(); (ch != '}'); ch = mygetc() ) {
  181.         /* Eat up the comment */
  182.         if( ch == EOF )
  183.             fatal( EOFMSG );
  184.         else if( ch == '"' )
  185.             /* Don't allow quoted comments to confuse us */
  186.             ch = getstring( s );
  187.         }    /* for */
  188.     }    /* if */
  189.     } /* for */
  190.     return ch;
  191. }
  192.  
  193. /*   */
  194.  
  195.     /***************************************************************\
  196.     *                                *
  197.     *    getstring( s ) - reads a quoted string from the infile,    *
  198.     *    approprately transforming escape sequences, and returns    *
  199.     *    the string in s.                    *
  200.     *                                *
  201.     \***************************************************************/
  202.  
  203. getstring( s )
  204. char    *s;
  205. {
  206.     int    ch, n;
  207.  
  208.     n = 0;
  209.     *s++ = '"';
  210.     for( ch = mygetc(); (ch != '"'); ch = mygetc() ) {
  211.     if( ++n == 511 )
  212.         error( "String too long.\n" );
  213.     if( ch == '\\' ) {
  214.         if( (ch = getescape()) == EOF )
  215.         fatal( EOFMSG );
  216.         if( n < 511 )
  217.         *s++ = ch;
  218.     }
  219.     else if( ch == EOF )
  220.         fatal( EOFMSG );
  221.     else {
  222.         if( ch == '\n' )
  223.         ch = ' ';
  224.         if( n < 511 )
  225.         *s++ = ch;
  226.     }
  227.     }
  228.     *s = '\0';
  229.     if( ch == EOF )
  230.     return EOF;
  231.     else
  232.     return ' ';
  233. }        /* getstring */
  234.  
  235.  
  236.     /***************************************************************\
  237.     *                                *
  238.     *    getescape() - reads an escape sequence such as \n or    *
  239.     *    \b or \033 from the infile and returns the translated    *
  240.     *    character.
  241.     *                                *
  242.     \***************************************************************/
  243.  
  244. getescape()
  245. {
  246.     int t, ch;
  247.     int count;
  248.  
  249.     ch = mygetc();
  250.     if( isdigit( ch ) ) {
  251.     count = 1;
  252.     t = ch - '0';
  253.     while( isdigit( ch = mygetc() ) && (count++ <= 3) )
  254.         t = t * '\010' + ch - '0';
  255.     if( ch != EOF )
  256.         ch = myunget( ch );
  257.     }
  258.     else
  259.     switch( ch ) {
  260.         case 'n'  : t = '\n'; break;
  261.         case 't'  : t = '\t'; break;
  262.         case 'b'  : t = '\b'; break;
  263.         case 'r'  : t = '\r'; break;
  264.         case 'f'  : t = '\f'; break;
  265.         case '\\' : t = '\\'; break;
  266.         default   : t = ch;
  267.     } /* switch */
  268.     return t;
  269. }
  270.  
  271. /* */
  272.  
  273.     /***************************************************************\
  274.     *                                *
  275.     *    Token type query routines.  These two routines verify    *
  276.     *    whether a token is of the appropriate type.  They are:    *
  277.     *                                *
  278.     *        isnumber( s ) - TRUE iff s is a decimal number    *
  279.     *        adlident( s ) - TRUE iff s is a legal ADL ident    *
  280.     *                                *
  281.     \***************************************************************/
  282.  
  283. isnumber( s )
  284. char    *s;
  285. {
  286.     if( *s == '-' )    /* Skip initial '-' */
  287.     s++;
  288.     while( *s )
  289.     if( !isdigit( *s ) )
  290.         return 0;
  291.     else
  292.         s++;
  293.     return 1;
  294. }
  295.  
  296.  
  297. adlident( s )
  298. char    *s;
  299. {
  300.     if( (*s == '$') || (*s == '.') || (*s == '_') || (*s == '-') )
  301.     s++;
  302.     if( !isalpha( *s ) )
  303.     return 0;
  304.     s++;
  305.     while( *s )
  306.     if( !(isalnum( *s ) || (*s == '_') || (*s == '-')) )
  307.         return 0;
  308.     else
  309.         s++;
  310.     return 1;
  311. }
  312.  
  313. /*   */
  314.  
  315.     /***************************************************************\
  316.     *                                *
  317.     *    These routines handle the actual i/o with the infile.    *
  318.     *    They keep track of the current line number.  They are:    *
  319.     *                                *
  320.     *        mygetc() - return the next char from infile    *
  321.     *        myunget( c ) - push c back into the infile    *
  322.     *                                *
  323.     \***************************************************************/
  324.  
  325. mygetc()
  326. {
  327.     int    result;
  328.     int breaker();
  329.  
  330.     result = getc( infile );
  331.     if( result == '\n' ) {
  332.     checkbreak( breaker );            /* Check for ^C */
  333.     numline++;
  334.     emit_file();
  335.     }
  336.     return result;
  337. }
  338.  
  339.  
  340. myunget( c )
  341. int    c;
  342. {
  343.     if( c == '\n' )
  344.     numline--;
  345.     return ungetc( c, infile );
  346. }
  347.  
  348.  
  349.     /***************************************************************\
  350.     *                                *
  351.     *    emit_file() - if debugging mode is set, and we are    *
  352.     *    compiling a routine, emit the file number and line    *
  353.     *    number into the code space, for better error tracking.    *
  354.     *                                *
  355.     \***************************************************************/
  356.  
  357. emit_file()
  358. {
  359.     if( debugging && inrout ) {
  360.     newcode( FILEN, filenum );
  361.     newcode( LINEN, numline );
  362.     }
  363. }
  364.  
  365. /*   */
  366.  
  367.     /***************************************************************\
  368.     *                                *
  369.     *    The following routines are here to hide the details    *
  370.     *    implementation of the input files from the routines    *
  371.     *     which use the lexer.  The routines are:        *
  372.     *                                *
  373.     *        open_input( name )    - open the infile    *
  374.     *        close_input()        - close the infile    *
  375.     *        save_input( &buf )    - save the infile    *
  376.     *        restore_input( buf )    - restore the infile    *
  377.     *                                *
  378.     \***************************************************************/
  379.  
  380. open_input( name )
  381. char     *name;
  382. {
  383.     infile = fopen( name, "r" );
  384.     if( infile == (FILE *)NULL )
  385.     return 0;
  386.     else
  387.     return 1;
  388. }
  389.  
  390.  
  391. close_input()
  392. {
  393.     fclose( infile );
  394. }
  395.  
  396.  
  397. save_input( buffer )
  398. char    **buffer;
  399. {
  400.     *buffer = (char *)infile;
  401. }
  402.  
  403.  
  404. restore_input( buffer )
  405. char    *buffer;
  406. {
  407.     infile = (FILE *)buffer;
  408. }
  409.  
  410. /*** EOF adllex.c ***/
  411.